/*
实验5-7 家谱处理
分数 30
作者 DS课程组
单位 浙江大学

人类学研究对于家族很感兴趣，于是研究人员搜集了一些家族的家谱进行研究。实验中，使用计算机处理家谱。为了实现这个目的，研究人员将家谱转换为文本文件。下面为家谱文本文件的实例：

LaoLi
  DaLi
    XiaoMing
    XiaoHong
  ErLi
    MeiMei

家谱文本文件中，每一行包含一个人的名字。第一行中的名字是这个家族最早的祖先。家谱仅包含最早祖先的后代，而他们的丈夫或妻子不出现在家谱中。每个人的子女比父母多缩进 2 个空格。以上述家谱文本文件为例，LaoLi 是这个家族最早的祖先，他有两个孩子 DaLi 和 ErLi，DaLi 有两个孩子 XiaoMing 和 XiaoHong，ErLi 只有一个孩子 MeiMei。

在实验中，研究人员还收集了家庭文件，并提取了家谱中有关两个人关系的陈述语句。下面为家谱中关系的陈述语句实例：

LaoLi is the parent of DaLi （老李与大李是父子关系）
DaLi is a sibling of ErLi  （大李与二李是兄弟姊妹关系）
MeiMei is a descendant of DaLi （梅梅是大李的后代）

研究人员需要判断每个陈述语句是真还是假，请编写程序帮助研究人员判断。
输入格式:

输入第 1 行给出 2 个正整数 n（2≤n≤100）和 m（≤100），其中 n 为家谱中名字的数量，m 为家谱中陈述语句的数量。

接下来输入的每行不超过 70 个字符。名字的字符串由不超过 10 个英文字母组成。在家谱中的第一行给出的名字前没有缩进空格。家谱中的其他名字至少缩进 2 个空格，即他们是家谱中最早祖先（第一行给出的名字）的后代，且如果家谱中一个名字前缩进 k 个空格，则下一行中名字至多缩进 k+2 个空格。

在一个家谱中同样的名字不会出现两次，且家谱中没有出现的名字不会出现在陈述语句中。每句陈述语句格式如下（括号内为解释文字，不是格式的一部分），其中 X 和 Y 为家谱中的不同名字：

X is a child of Y （X是Y的孩子）
X is the parent of Y （X是Y的父母）
X is a sibling of Y （X是Y的兄弟姊妹）
X is a descendant of Y （X是Y的后代）
X is an ancestor of Y （X是Y的祖先）

输出格式:

对于测试用例中的每句陈述语句，如果陈述为真，在一行中输出 True；如果陈述为假，在一行中输出 False。
输入样例:

6 5
LaoLi
  DaLi
    XiaoMing
    XiaoHong
  ErLi
    MeiMei
DaLi is a child of LaoLi
DaLi is an ancestor of XiaoHong
DaLi is a sibling of ErLi
ErLi is the parent of XiaoMing
LaoLi is a descendant of XiaoHong

输出样例:

True
True
True
False
False
*/

#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <map>

using namespace std;

void buildFamilyTree(map<string, string> &name2Parent, int n) {
    stack<pair<string, string>> parentStack;

    string parent;
    getline(cin, parent);
    
    name2Parent[parent] = "";
    parentStack.push({parent, ""});

    string indentAdd = "  ";
    string indent = "";
    string childIndent = indent + indentAdd;
    for (int i = 1; i < n; i++) {
        string name;
        getline(cin, name);
        if (name.size() > childIndent.size() && name.substr(0, childIndent.size()) == childIndent) {
            name = name.substr(childIndent.size());
            name2Parent[name] = parentStack.top().first;
            parentStack.push({name, childIndent});
            indent = childIndent;
            childIndent += indentAdd;
        } else if (name.size() > indent.size() && name.substr(0, indent.size()) == indent) {
            parentStack.pop();
            name = name.substr(indent.size());
            name2Parent[name] = parentStack.top().first;
            parentStack.push({name, indent});
        } else {
            pair<string, string> p = parentStack.top();
            while (true) {
                p = parentStack.top();
                if (name.size() > p.second.size() && name.substr(0, p.second.size()) == p.second) {
                    break;
                }
                parentStack.pop();
            }
            indent = p.second;
            childIndent = indent + indentAdd;
            name = name.substr(indent.size());

            parentStack.pop();
            p = parentStack.top();
            
            name2Parent[name] = p.first;
            parentStack.push({name, indent});
        }
    }
}

bool check(const map<string, string> &name2Parent, string line) {
    string name1, name2, relation;
    int pos = 0;
    auto end = line.find(" ");
    name1 = line.substr(0, end);
    pos = line.find_last_of(" ");
    name2 = line.substr(pos + 1);
    
    if (line.find("child") != string::npos) {
        return name2Parent.at(name1) == name2;
    } 
    if (line.find("parent") != string::npos) {
        return name2Parent.at(name2) == name1;
    }
    if (line.find("sibling") != string::npos) {
        return name2Parent.at(name1) == name2Parent.at(name2);
    }
    if (line.find("ancestor") != string::npos) {
        string parent = name2Parent.at(name2);
        while (parent != name1 && parent != "") {
            parent = name2Parent.at(parent);
        }
        return parent == name1;
    }
    if (line.find("descendant") != string::npos) {
        string parent = name2Parent.at(name1);
        while (parent != name2 && parent != "") {
            parent = name2Parent.at(parent);
        }
        return parent == name2;
    }
    return false;
}

int main() {
    int n, m;
    cin >> n >> m;
    cin.get();
    map<string, string> name2Parent;
    buildFamilyTree(name2Parent, n);
    // cin.get();
    for (int i = 0; i < m; i++) {
        string line;
        getline(cin, line);
        cout << (check(name2Parent, line) ? "True" : "False") << endl;
    }
    return 0;
}